#pragma once
#include<string>
#include"utils.hpp"
#include"logger.hpp"
#include<vector>
#include<memory>
#include<utility>
#include<iostream>
#include<unordered_map>

#define KEY_RCODE "rcode"
#define KEY_RESULT "result"
#define KEY_METHOD "method"
#define KEY_PARAMETERS "parameters"
#define KEY_TOPIC "topic"
#define KEY_OPTYPE "optype"
#define KEY_CONTENT "content"
#define KEY_HOST "host"
#define KEY_IP "ip"
#define KEY_PORT "port"

// 消息类型
enum class MSG_Type  // 强类型枚举
{
    // RPC 服务
    RPC_REQ,
    RPC_RES,
    // 主题服务(发布和订阅)
    TOPIC_REQ,
    TOPIC_RES,
    // 服务上下线/注册和发现
    SERVICE_REQ,
    SERVICE_RES,

    // 增加消息类型：服务端主动向客户端发送的通知 (推送)
    SERVICE_NOTIFY,
    TOPIC_NOTIFY
};

// 主题操作
enum class TOPIC_OPTYPE
{
    // 创建 删除 发布 订阅
    CREATE,
    DELETE,
    PUBLISH,
    SUBSCRIBE
};

// 服务注册 上线 发现 下线
enum class SERVICE_OPTYPE
{
    REGISTER,
    ONLINE,
    OFFLINE,
    DISCOVERY
};

// 响应返回码
enum class RCode
{
    OK,
    PARSE_FAILED,
    DISCONNECTED,
    INVALID_PARAMS,
    NOT_FOUND_SERVICE,
    NOT_FOUND_TOPIC,
    NOT_FOUND_METHOD,
    NOT_FOUND_SERVICE_ADDRESS,
    INVALID_OPTYPE,
    NOT_SET_Handler,
    CHECK_FAILED,
    REGISTER_FAILED,
};

static std::unordered_map<RCode, std::string> errStr = {{RCode::PARSE_FAILED, "消息解析失败"},
                                                        {RCode::DISCONNECTED, "连接断开"},
                                                        {RCode::INVALID_PARAMS, "无效参数"},
                                                        {RCode::NOT_FOUND_SERVICE, "没有找到对应的服务方法"},
                                                        {RCode::NOT_FOUND_TOPIC, "没有找到对应的主题"},
                                                        {RCode::NOT_FOUND_METHOD, "没有找到对应的rpc调用"},
                                                        {RCode::INVALID_OPTYPE, "无效的操作"},
                                                        {RCode::NOT_SET_Handler, "没有设置对应的处理回调"},
                                                        {RCode::CHECK_FAILED, "校验失败"},
                                                        {RCode::REGISTER_FAILED, "服务注册上线失败"},
                                                        {RCode::NOT_FOUND_SERVICE_ADDRESS,"没有找到服务对应的地址"}};


// ------------------------------------------- 消息体抽象 --------------------------
class BaseMessage
{
public:
    using ptr = std::shared_ptr<BaseMessage>;
    void setType(const MSG_Type type) { _mtype = type;}
    const MSG_Type getType() {return _mtype;}

    void setId(const std::string& id = "") 
    { 
        if (id.empty()) _id = UUID::generate_uuid_v4();
        else _id = id;
    }
    std::string getId() {return _id;}
    
    virtual bool serialize(std::string& outStr) = 0;
    virtual bool unserialize(const std::string& inStr, std::string& err) = 0;
    virtual bool check() = 0;
    virtual ptr clone() = 0;

    virtual ~BaseMessage() {}
    BaseMessage() {}
private:
    MSG_Type _mtype;
    std::string _id = "";
};

// 工厂类构造消息对象
class MessageFactory
{
public:
    template<typename T, typename ...Args>
    static std::shared_ptr<T> create(Args&& ...args)
    {
        return std::make_shared<T>(std::forward<Args>(args)...);
    }
};

class JsonMessage : public BaseMessage
{
public:
    using ptr = std::shared_ptr<JsonMessage>;
    virtual bool serialize(std::string &outStr) override
    {
        return JsopRpc::Serialize(_body, outStr);
    }

    virtual bool unserialize(const std::string &inStr, std::string &err) override
    {
        return JsopRpc::UnSerialize(inStr, _body, err);
    }

    virtual bool check() override {return false;}

    virtual ~JsonMessage() {}
    JsonMessage() {}
protected:
    Json::Value _body;
};

class JsonRequest : public JsonMessage 
{
public:
    using ptr = std::shared_ptr<JsonRequest>;
    virtual ~JsonRequest() {}
    JsonRequest() {}
};

class JsonResponse : public JsonMessage {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        void setRcode(const RCode rcode) {_body[KEY_RCODE] = static_cast<int>(rcode);}
        const RCode getRcode() {return static_cast<RCode>(_body[KEY_RCODE].asInt());}

        virtual ~JsonResponse() {}
        JsonResponse() {}
};

// 具体的请求/响应类型
class RPCRequest : public JsonRequest
{
    // 请求方法 -- 字符串 ； 参数 --- 对象
public:
    using ptr = std::shared_ptr<RPCRequest>;
    virtual ~RPCRequest() {}
    RPCRequest() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<RPCRequest>();
    }

    virtual bool check() override
    {
        if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
        {
            LOG_ERROR << "RPC请求方法字段不存在或类型错误";
            return false;
        }

        if (_body[KEY_PARAMETERS].isNull() || !_body[KEY_PARAMETERS].isObject())
        {
            LOG_ERROR << "RPC请求参数字段不存在或类型错误";
            return false;
        }
        return true;
    }

    void setMethod(const std::string& method) {_body[KEY_METHOD] = method;}
    const std::string getMethod() {return _body[KEY_METHOD].asString();}

    void setParameters(const Json::Value& val) {_body[KEY_PARAMETERS] = val;}
    const Json::Value getParameters() {return _body[KEY_PARAMETERS];}
};

class TopicRequest : public JsonRequest
{
    // 操作方式；主题；内容
public:
    using ptr = std::shared_ptr<TopicRequest>;
    virtual ~TopicRequest() {}
    TopicRequest() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<TopicRequest>();
    }


    virtual bool check() override
    {
        if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
        {
            LOG_ERROR << "Topic请求方法不存在或字段类型错误";
            return false;
        }
        if (_body[KEY_TOPIC].isNull() || !_body[KEY_TOPIC].isString())
        {
            LOG_ERROR << "Topic请求没有指定主题或字段类型错误";
            return false;
        }
        if (_body[KEY_OPTYPE].asInt() == static_cast<int>(TOPIC_OPTYPE::PUBLISH) && (_body[KEY_CONTENT].isNull() || !_body[KEY_CONTENT].isString()))
        {
            LOG_ERROR << "Topic请求发布的内容不存在或类型错误";
            return false;
        }
        return true;
    }

    void setOptype(const TOPIC_OPTYPE op) {_body[KEY_OPTYPE] = static_cast<int>(op);}
    const TOPIC_OPTYPE getOptype() {return static_cast<TOPIC_OPTYPE>(_body[KEY_OPTYPE].asInt());}

    void setTopic(const std::string& topic) {_body[KEY_TOPIC] = topic;}
    const std::string getTopic() {return _body[KEY_TOPIC].asString();}

    void setContent(const std::string& content) {_body[KEY_CONTENT] = content;}
    const std::string getContent() {return _body[KEY_CONTENT].asString();}
};


using Address = std::pair<std::string, uint16_t>;

std::string AddressToString(const Address& add)
{
    return std::string(add.first + ":" + std::to_string(add.second));
}

class ServiceRequest : public JsonRequest
{
public:
    using ptr = std::shared_ptr<ServiceRequest>;
    virtual ~ServiceRequest() {}
    ServiceRequest() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<ServiceRequest>();
    }

    virtual bool check() override
    {
        if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
        {
            LOG_ERROR << "Service服务的操作方法不存在或类型错误";
            return false;
        }
        if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
        {
            LOG_ERROR << "Service服务的方法字段不存在或类型错误";
            return false;
        }

        if (_body[KEY_OPTYPE].asInt() == (int)SERVICE_OPTYPE::DISCOVERY)
        {
            return true;
        }

        if ( // 服务发现请求没有主机信息
            (_body[KEY_HOST].isNull() || !_body[KEY_HOST].isObject()) || 
            (_body[KEY_HOST][KEY_IP].isNull() || !_body[KEY_HOST][KEY_IP].isString()) || 
            (_body[KEY_HOST][KEY_PORT].isNull() || !_body[KEY_HOST][KEY_PORT].isIntegral()))
            {
                LOG_ERROR << "Service服务的主机字段不存在或类型错误";
                return false;
            }
        return true;
    }

    void setMethod(const std::string& method) {_body[KEY_METHOD] = method;}
    const std::string getMethod() {return _body[KEY_METHOD].asString();}

    void setHost(const Address& host) 
    {
        Json::Value val;
        val[KEY_IP] = host.first;
        val[KEY_PORT] = host.second;
        _body[KEY_HOST] = val;
    }
    const Address getHost() 
    {   
        return {_body[KEY_HOST][KEY_IP].asString(), _body[KEY_HOST][KEY_PORT].asInt()};
    }

    void setOptype(const SERVICE_OPTYPE op) {_body[KEY_OPTYPE] = static_cast<int>(op);}
    const SERVICE_OPTYPE getOptype() {return static_cast<SERVICE_OPTYPE>(_body[KEY_OPTYPE].asInt());}
};

// -----------------------------------------------
class RpcResponse : public JsonResponse
{
    // 返回码 + result
public:
    using ptr = std::shared_ptr<RpcResponse>;
    virtual ~RpcResponse() {}
    RpcResponse() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<RpcResponse>();
    }

    virtual bool check() override
    {
        if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
        {
            LOG_ERROR << "RPC响应状态码不存在或类型错误";
            return false;
        }
        if (_body[KEY_RESULT].isNull() || !_body[KEY_RESULT].isObject())
        {
            LOG_ERROR << "RPC响应结果不存在或类型错误";
            return false;
        }
        return true;
    }

    void setResult(const Json::Value& resul) {_body[KEY_RESULT] = resul;}
    const Json::Value getResult() {return _body[KEY_RESULT];}
};

class TopicResponse : public JsonResponse
{
public:
    using ptr = std::shared_ptr<TopicResponse>;
    virtual ~TopicResponse() {}
    TopicResponse() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<TopicResponse>();
    }

    virtual bool check() override
    {
        if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
        {
            LOG_ERROR << "响应状态码不存在或类型错误";
            return false;
        }
        return true;
    }
};

class ServiceResponse : public JsonResponse
{
public:
    using ptr = std::shared_ptr<ServiceResponse>;
    virtual ~ServiceResponse() {}
    ServiceResponse() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<ServiceResponse>();
    }

    virtual bool check() override
    {
        if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
        {
            LOG_ERROR << "Service响应状态码不存在或类型错误";
            return false;
        }
        if (_body[KEY_OPTYPE].asInt() == static_cast<int>(SERVICE_OPTYPE::DISCOVERY))
        {
            if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
            {
                LOG_ERROR << "service服务发现响应对应的方法字段不存在或类型错误";
                return false;
            }

            if (_body[KEY_HOST].isNull() || !_body[KEY_HOST].isArray())
            {
                LOG_ERROR << "Service服务发现响应主机字段不存在或类型错误";
                return false;
            }

            int sz = _body[KEY_HOST].size();
            for (int i = 0; i < sz; ++i)
            {
                if ((_body[KEY_HOST][i][KEY_IP].isNull() || !_body[KEY_HOST][i][KEY_IP].isString()) || 
                    (_body[KEY_HOST][i][KEY_PORT].isNull() || !_body[KEY_HOST][i][KEY_PORT].isIntegral()))
                    {
                        LOG_ERROR << "Service服务发现响应中没有具体的ip:port字段或类型错误";
                        return false;
                    }
            }
        }
        
        return true;
    }

    void setOptype(const SERVICE_OPTYPE op) {_body[KEY_OPTYPE] = static_cast<int>(op);}
    const SERVICE_OPTYPE getOptype() {return static_cast<SERVICE_OPTYPE>(_body[KEY_OPTYPE].asInt());}

    // 服务发现
    void setMethod(const std::string& method) {_body[KEY_METHOD] = method;}
    const std::string getMethod() {return _body[KEY_METHOD].asString();}

    void setHosts(const std::vector<Address>& hosts)
    {
        if (hosts.empty())
        {
            // 构造无效字段，配合整体的字段检查功能
            Json::Value val;
            val[KEY_IP] = "none";
            val[KEY_PORT] = 0;
            _body[KEY_HOST].append(val);
            return;
        }

        for (auto& e : hosts)
        {
            Json::Value val;
            val[KEY_IP] = e.first;
            val[KEY_PORT] = e.second;
            _body[KEY_HOST].append(val);
        }
        
        // int sz = hosts.size();
        // for (int i = 0; i < sz; ++i)
        // {
        //     LOG_DEBUG << _body[KEY_HOST][i][KEY_IP].asString() << ": " << _body[KEY_HOST][i][KEY_PORT].asInt();
        // }

    }

    const std::vector<Address> getHosts()
    {
        std::vector<Address> addrs;
        int sz = _body[KEY_HOST].size();
        for (int i = 0; i < sz; ++i)
        {
            addrs.emplace_back(_body[KEY_HOST][i][KEY_IP].asString(), _body[KEY_HOST][i][KEY_PORT].asInt());
        }
        return addrs;
    }
};

// 主动推送
class ServiceNotify : public ServiceRequest
{
public:
    using ptr = std::shared_ptr<ServiceNotify>;
    ServiceNotify() {}
    virtual ~ServiceNotify() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<ServiceNotify>();
    }

};

class TopicNotify : public TopicRequest
{
public:
    using ptr = std::shared_ptr<TopicNotify>;
    TopicNotify() {}
    virtual ~TopicNotify() {}

    virtual BaseMessage::ptr clone() override
    {
        return MessageFactory::create<TopicNotify>();
    }
};

static std::unordered_map<MSG_Type, BaseMessage::ptr> MessageTypes = {{MSG_Type::RPC_REQ, MessageFactory::create<RPCRequest>()}, {MSG_Type::RPC_RES, MessageFactory::create<RpcResponse>()}, 
                        {MSG_Type::SERVICE_REQ, MessageFactory::create<ServiceRequest>()}, {MSG_Type::SERVICE_RES, MessageFactory::create<ServiceResponse>()}, 
                        {MSG_Type::TOPIC_REQ, MessageFactory::create<TopicRequest>()}, {MSG_Type::TOPIC_RES, MessageFactory::create<TopicResponse>()},
                        {MSG_Type::SERVICE_NOTIFY, MessageFactory::create<ServiceNotify>()}, {MSG_Type::TOPIC_NOTIFY, MessageFactory::create<TopicNotify>()}};